<script setup lang="ts">
/**
 * 资产标签生成器组件
 * 用于生成带有二维码的资产标签，支持自定义尺寸和布局
 * 
 * 主要功能：
 * 1. 根据资产信息生成二维码标签
 * 2. 支持自定义标签尺寸、页面布局
 * 3. 提供打印预览功能
 * 4. 支持批量生成多个资产标签
 */

// 国际化支持
import { useI18n } from "vue-i18n";
// 导入页面标题设置工具
import { useHead } from 'nuxt/app';
// HTML内容净化，防止XSS攻击
import DOMPurify from "dompurify";
// API路由工具
import { route } from "../../lib/api/base";
// UI组件导入
import { toast, Toaster } from "@/components/ui/sonner";
import { Separator } from "@/components/ui/separator";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";

// 获取国际化函数
const { t } = useI18n();

// 页面元数据配置
definePageMeta({
  middleware: ["auth"],  // 需要身份验证
  layout: "default",    // 使用默认布局

});

// 页面标题由默认布局统一设置，此处不再重复设置

// API实例
const api = useUserApi();

// 是否显示标签边框
const bordered = ref(false);

/**
 * 显示属性配置
 * 控制标签生成器的各种参数设置
 */
const displayProperties = reactive({
  baseURL: window.location.origin,    // 网站基础URL，用于生成二维码
  assetRange: 1,                      // 起始资产ID
  assetRangeMax: 91,                  // 结束资产ID
  measure: "in",                      // 尺寸单位（in=英寸，cm=厘米，mm=毫米）
  gapY: 0.25,                         // 垂直间距
  columns: 3,                         // 每页列数
  cardHeight: 1,                      // 单个标签高度（英寸）
  cardWidth: 2.63,                    // 单个标签宽度（英寸）
  pageWidth: 8.5,                     // 页面总宽度（标准A4纸）
  pageHeight: 11,                     // 页面总高度（标准A4纸）
  pageTopPadding: 0.52,               // 页面上边距
  pageBottomPadding: 0.42,            // 页面下边距
  pageLeftPadding: 0.25,              // 页面左边距
  pageRightPadding: 0.1,              // 页面右边距
});

/**
 * 标签计算输入参数接口
 * 定义计算标签布局所需的输入数据
 */
type LabelOptionInput = {
  measure: string;                    // 尺寸单位
  page: {
    height: number;                   // 页面高度
    width: number;                    // 页面宽度
    pageTopPadding: number;           // 页面上边距
    pageBottomPadding: number;        // 页面下边距
    pageLeftPadding: number;          // 页面左边距
    pageRightPadding: number;         // 页面右边距
  };
  cardHeight: number;                 // 标签高度
  cardWidth: number;                  // 标签宽度
};

/**
 * 标签计算输出接口
 * 定义计算后的标签布局数据
 */
type Output = {
  measure: string;                    // 尺寸单位
  cols: number;                       // 每页列数
  rows: number;                       // 每页行数
  gapY: number;                       // 垂直间距
  gapX: number;                       // 水平间距
  card: {
    width: number;                    // 实际标签宽度
    height: number;                   // 实际标签高度
  };
  page: {
    width: number;                    // 页面宽度
    height: number;                   // 页面高度
    pt: number;                       // 顶部内边距
    pb: number;                       // 底部内边距
    pl: number;                       // 左侧内边距
    pr: number;                       // 右侧内边距
  };
};

/**
 * 计算网格布局数据
 * 根据输入参数计算标签在页面上的最佳布局
 * @param input - 标签计算输入参数
 * @returns 计算后的标签布局数据
 */
function calculateGridData(input: LabelOptionInput): Output {
  const { page, cardHeight, cardWidth } = input;

  // 验证并标准化尺寸单位
  const measureRegex = /in|cm|mm/;
  const measure = measureRegex.test(input.measure) ? input.measure : "in";

  // 计算可用的页面宽度和高度（减去边距）
  const availablePageWidth = page.width - page.pageLeftPadding - page.pageRightPadding;
  const availablePageHeight = page.height - page.pageTopPadding - page.pageBottomPadding;

  // 验证页面尺寸是否足够容纳标签
  if (availablePageWidth < cardWidth || availablePageHeight < cardHeight) {
    toast.error(t("reports.label_generator.toast.page_too_small_card"));
    return out.value;
  }

  // 计算每页可以容纳的列数和行数
  const cols = Math.floor(availablePageWidth / cardWidth);
  const rows = Math.floor(availablePageHeight / cardHeight);
  
  // 计算标签之间的间距，使布局更美观
  const gapX = (availablePageWidth - cols * cardWidth) / (cols - 1);
  const gapY = (page.height - rows * cardHeight) / (rows - 1);

  return {
    measure,
    cols,
    rows,
    gapX,
    gapY,
    card: {
      width: cardWidth,
      height: cardHeight,
    },
    page: {
      width: page.width,
      height: page.height,
      pt: page.pageTopPadding,
      pb: page.pageBottomPadding,
      pl: page.pageLeftPadding,
      pr: page.pageRightPadding,
    },
  };
}

/**
 * 输入字段定义接口
 * 定义控制面板中各个输入字段的配置信息
 */
interface InputDef {
  label: string;                      // 字段标签文本
  ref: keyof typeof displayProperties; // 对应displayProperties中的属性名
  type?: "number" | "text";           // 输入类型（数字或文本）
}

/**
 * 计算输入字段配置
 * 根据国际化文本生成控制面板的输入字段配置
 */
const propertyInputs = computed<InputDef[]>(() => {
  return [
    {
      label: t("reports.label_generator.asset_start"),  // 起始资产
      ref: "assetRange",
    },
    {
      label: t("reports.label_generator.asset_end"),   // 结束资产
      ref: "assetRangeMax",
    },
    {
      label: t("reports.label_generator.measure_type"), // 单位类型
      ref: "measure",
      type: "text",
    },
    {
      label: t("reports.label_generator.label_height"), // 标签高度
      ref: "cardHeight",
    },
    {
      label: t("reports.label_generator.label_width"),  // 标签宽度
      ref: "cardWidth",
    },
    {
      label: t("reports.label_generator.page_width"),   // 页面宽度
      ref: "pageWidth",
    },
    {
      label: t("reports.label_generator.page_height"),  // 页面高度
      ref: "pageHeight",
    },
    {
      label: t("reports.label_generator.page_top_padding"), // 上边距
      ref: "pageTopPadding",
    },
    {
      label: t("reports.label_generator.page_bottom_padding"), // 下边距
      ref: "pageBottomPadding",
    },
    {
      label: t("reports.label_generator.page_left_padding"), // 左边距
      ref: "pageLeftPadding",
    },
    {
      label: t("reports.label_generator.page_right_padding"), // 右边距
      ref: "pageRightPadding",
    },
    {
      label: t("reports.label_generator.base_url"),     // 基础URL
      ref: "baseURL",
      type: "text",
    },
  ];
});

/**
 * 标签数据接口
 * 定义单个标签需要显示的数据结构
 */
type LabelData = {
  url: string;        // 二维码URL
  name: string;       // 资产名称
  assetID: string;    // 格式化资产ID
  location: string;   // 所在位置
};

/**
 * 格式化资产ID
 * 将数字转换为标准格式（如123456 -> 123-456）
 * @param aid - 资产ID（数字或字符串）
 * @returns 格式化后的资产ID
 */
function fmtAssetID(aid: number | string) {
  aid = aid.toString();

  // 补零到6位，然后添加分隔符
  let aidStr = aid.toString().padStart(6, "0");
  aidStr = aidStr.slice(0, 3) + "-" + aidStr.slice(3);
  return aidStr;
}

/**
 * 生成二维码URL
 * 根据资产ID生成包含完整链接的二维码URL
 * @param assetID - 资产ID
 * @returns 二维码图片URL
 */
function getQRCodeUrl(assetID: string): string {
  let origin = displayProperties.baseURL.trim();

  // 移除末尾的斜杠
  if (origin.endsWith("/")) {
    origin = origin.slice(0, -1);
  }

  // 构建完整的资产链接
  const data = `${origin}/a/${assetID}`;

  // 调用后端API生成二维码，设置合适的尺寸
  return route(`/qrcode`, { data: encodeURIComponent(data), size: 256 });
}

/**
 * 获取标签数据
 * 根据资产信息生成标签显示数据
 * @param n - 索引号
 * @param item - 资产信息对象或null
 * @returns 标签显示数据
 */
function getItem(n: number, item: { assetId: string; name: string; location: { name: string } } | null): LabelData {
  // 格式化资产ID（补零并添加分隔符）
  const assetID = fmtAssetID(item?.assetId ?? n + 1);

  return {
    url: getQRCodeUrl(assetID),                   // 二维码URL
    assetID: item?.assetId ?? assetID,            // 资产ID
    name: item?.name ?? "_______________",        // 资产名称（无数据时显示下划线）
    location: item?.location?.name ?? "_______________", // 所在位置（无数据时显示下划线）
  };
}

const { data: allFields } = await useAsyncData(async () => {
  const { data, error } = await api.items.getAll({ orderBy: "assetId" });

  if (error) {
    return {
      items: [],
    };
  }

  return data;
});

const items = computed(() => {
  if (displayProperties.assetRange > displayProperties.assetRangeMax) {
    return [];
  }

  const diff = displayProperties.assetRangeMax - displayProperties.assetRange;

  if (diff > 999) {
    return [];
  }

  const items: LabelData[] = [];
  for (let i = displayProperties.assetRange - 1; i < displayProperties.assetRangeMax - 1; i++) {
    const item = allFields?.value?.items?.[i];
    if (item?.location) {
      items.push(getItem(i, item as { assetId: string; location: { name: string }; name: string }));
    } else {
      items.push(getItem(i, null));
    }
  }
  return items;
});

type Row = {
  items: LabelData[];
};

type Page = {
  rows: Row[];
};

const pages = ref<Page[]>([]);

const out = ref({
  measure: "in",
  cols: 0,
  rows: 0,
  gapY: 0,
  gapX: 0,
  card: {
    width: 0,
    height: 0,
  },
  page: {
    width: 0,
    height: 0,
    pt: 0,
    pb: 0,
    pl: 0,
    pr: 0,
  },
});

/**
 * 计算并生成页面布局
 * 根据当前设置参数重新计算页面布局并生成预览
 */
function calcPages() {
  // 设置输出尺寸
  out.value = calculateGridData({
    measure: displayProperties.measure,
    page: {
      height: displayProperties.pageHeight,
      width: displayProperties.pageWidth,
      pageTopPadding: displayProperties.pageTopPadding,
      pageBottomPadding: displayProperties.pageBottomPadding,
      pageLeftPadding: displayProperties.pageLeftPadding,
      pageRightPadding: displayProperties.pageRightPadding,
    },
    cardHeight: displayProperties.cardHeight,
    cardWidth: displayProperties.cardWidth,
  });

  const calc: Page[] = [];

  const perPage = out.value.rows * out.value.cols;

  const itemsCopy = [...items.value];

  while (itemsCopy.length > 0) {
    const page: Page = {
      rows: [],
    };

    for (let i = 0; i < perPage; i++) {
      const item = itemsCopy.shift();
      if (!item) {
        break;
      }

      if (i % out.value.cols === 0) {
        page.rows.push({
          items: [],
        });
      }

      page.rows[page.rows.length - 1].items.push(item);
    }

    calc.push(page);
  }

  pages.value = calc;
}

// 组件挂载时自动计算页面布局
onMounted(() => {
  calcPages();
});

/**
 * 打印功能
 * 调用浏览器打印功能打印当前标签页面
 */
function print() {
  window.print();
}
</script>

<template>
  <div class="p-6">
    <!-- 页面头部说明区域：打印时隐藏 -->
    <div class="print:hidden mb-8">
      <div class="prose max-w-none">
        <h1>HomeBox {{ $t("reports.label_generator.title") }}</h1>
      <p>
        {{ $t("reports.label_generator.instruction_1") }}
      </p>
      <p>
        {{ $t("reports.label_generator.instruction_2") }}
      </p>
      <p v-html="DOMPurify.sanitize($t('reports.label_generator.instruction_3'))"></p>
      
      <!-- 使用提示 -->
      <h2>{{ $t("reports.label_generator.tips") }}</h2>
      <ul>
        <li v-html="DOMPurify.sanitize($t('reports.label_generator.tip_1'))"></li>
        <li v-html="DOMPurify.sanitize($t('reports.label_generator.tip_2'))"></li>
        <li v-html="DOMPurify.sanitize($t('reports.label_generator.tip_3'))"></li>
      </ul>
      
      <!-- 导航链接 -->
      <div class="flex flex-wrap gap-3 mt-4">
        <NuxtLink href="/tools" class="inline-flex items-center px-4 py-2 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors">
          {{ $t("menu.tools") }}
        </NuxtLink>
        <NuxtLink href="/home" class="inline-flex items-center px-4 py-2 rounded-md bg-secondary text-secondary-foreground hover:bg-secondary/90 transition-colors">
          {{ $t("menu.home") }}
        </NuxtLink>
      </div>
    </div>
  </div>
    
    <!-- 分隔线 -->
    <div class="my-6">
      <Separator />
    </div>

    <!-- 设置面板 -->
    <div class="bg-white rounded-lg shadow-md p-6 mb-8">
      <h2 class="text-xl font-bold mb-4">{{ $t('reports.label_generator.settings') }}</h2>
      <!-- 设置输入区域：网格布局显示所有设置项 -->
      <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6">
        <div v-for="(prop, i) in propertyInputs" :key="i" class="flex flex-col">
          <Label :for="`input-${prop.ref}`" class="mb-1 font-medium text-sm">
            {{ prop.label }}
          </Label>
          <Input
            :id="`input-${prop.ref}`"
            v-model="displayProperties[prop.ref]"
            :type="prop.type ? prop.type : 'number'"
            step="0.01"
            :placeholder="$t('reports.label_generator.input_placeholder')"
            class="w-full"
          />
        </div>
      </div>

      <!-- 边框显示开关 -->
      <div class="mb-6">
        <div class="flex items-center gap-2 py-4">
          <Checkbox id="borderedLabels" v-model="bordered" />
          <Label class="cursor-pointer" for="borderedLabels">
            {{ $t("reports.label_generator.bordered_labels") }}
          </Label>
        </div>
      </div>

      <!-- 操作按钮区域 -->
      <div class="mt-6">
        <p class="text-sm text-gray-500 mb-4">{{ $t("reports.label_generator.qr_code_example") }} {{ displayProperties.baseURL }}/a/{asset_id}</p>
        <Button size="lg" class="w-full bg-primary hover:bg-primary/90 transition-colors"
          @click="calcPages">
          {{ $t("reports.label_generator.generate_page") }}
        </Button>
      </div>
    </div>
  </div>

  <!-- 标签打印预览区域 -->
  <div class="container mx-auto mt-8 mb-16">
    <div class="flex flex-col items-center">
      <!-- 单个页面：根据计算结果动态生成 -->
      <section
        v-for="(page, pi) in pages"
        :key="pi"
        class="mb-8 border-2 print:border-none shadow-md"
        :style="{
          paddingTop: `${out.page.pt}${out.measure}`,
          paddingBottom: `${out.page.pb}${out.measure}`,
          paddingLeft: `${out.page.pl}${out.measure}`,
          paddingRight: `${out.page.pr}${out.measure}`,
          width: `${out.page.width}${out.measure}`,
          background: `white`,
          color: `black`,
        }"
      >
        <!-- 标签行：按行排列标签 -->
        <div
          v-for="(row, ri) in page.rows"
          :key="ri"
          class="flex flex-wrap break-inside-avoid mb-4"
          :style="{
            columnGap: `${out.gapX}${out.measure}`,
            rowGap: `${out.gapY}${out.measure}`,
          }"
        >
          <!-- 单个标签：包含二维码和资产信息 -->
          <div
            v-for="(item, idx) in row.items"
            :key="idx"
            class="flex border-2 rounded"
            :class="{
              'border-black': bordered,
              'border-transparent': !bordered,
            }"
            :style="{
              height: `${out.card.height}${out.measure}`,
              width: `${out.card.width}${out.measure}`,
            }"
          >
            <!-- 二维码图片区域 -->
            <div class="flex items-center p-2">
              <img
                :src="item.url"
                :alt="`资产${item.assetID}二维码`"
                :style="{
                  minWidth: `${out.card.height * 0.8}${out.measure}`,
                  width: `${out.card.height * 0.8}${out.measure}`,
                  height: `${out.card.height * 0.8}${out.measure}`,
                }"
                class="rounded"
              />
            </div>
            
            <!-- 资产信息区域 -->
            <div class="ml-2 flex flex-col justify-center p-2 flex-1">
              <div class="font-bold text-sm truncate">{{ item.assetID }}</div>          <!-- 资产ID -->
              <div class="text-xs font-light italic text-gray-500">HomeBox</div>     <!-- 系统标识 -->
              <div class="overflow-hidden text-wrap text-xs truncate">{{ item.name }}</div> <!-- 资产名称 -->
              <div class="text-xs text-gray-600 truncate">{{ item.location }}</div>          <!-- 所在位置 -->
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>

<style scoped>
/* 打印样式优化：隐藏非打印元素，确保打印效果 */
@media print {
  /* 隐藏所有页面元素 */
  body * {
    visibility: hidden;
  }
  
  /* 显示打印区域及其内容 */
  .page,
  .page * {
    visibility: visible;
  }
  
  /* 固定打印区域位置 */
  .page {
    position: absolute;
    left: 0;
    top: 0;
  }
}

/* 打印区域样式：确保打印效果 */
section {
  margin-bottom: 2rem;    /* 页面间距 */
  page-break-after: always; /* 打印时强制分页 */
}

/* 最后一个页面不需要分页 */
section:last-child {
  page-break-after: avoid;
}

/* 标签边框样式：根据设置显示或隐藏 */
.border-2 {
  border-width: 2px;
}

.border-black {
  border-color: black;
}

.border-transparent {
  border-color: transparent;
}

/* 响应式布局：确保在不同设备上的显示效果 */
@media (max-width: 768px) {
  .grid-cols-2 {
    grid-template-columns: 1fr; /* 移动端单列显示 */
  }
}
</style>
